package com.zyx.concurrentdemo.c08utils;

import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.*;

import static com.zyx.concurrentdemo.c02basic.util.Sleeper.sleep;

/**
 * @author Yaxi.Zhang
 * @since 2021/10/21 10:20
 * desc: CyclicBarrier案例
 */
@Slf4j(topic = "c.TestCyclicBarrier")
public class TestCyclicBarrier {

    public static void main(String[] args) {
        // 注意线程数与 CyclicBarrier 中的parties数目应该保持一致, 否则会出现执行属性不一致的情况
        ExecutorService service = Executors.newFixedThreadPool(2);
        CyclicBarrier barrier = new CyclicBarrier(2, ()-> log.debug("task1, task2 finish..."));
        for (int i = 0; i < 3; i++) {
            log.debug("await number before: {}", barrier.getNumberWaiting());
            service.submit(() -> {
                log.debug("task1 begin...");
                sleep(1);
                try {
                    barrier.await(); // 2-1=1
                } catch (InterruptedException | BrokenBarrierException ex) {
                    log.error("exception: [{}]", ex.getMessage(), ex);
                }
            });
            service.submit(() -> {
                log.debug("task2 begin...");
                sleep(2);
                try {
                    barrier.await(); // 1-1=0
                } catch (InterruptedException | BrokenBarrierException ex) {
                    log.error("exception: [{}]", ex.getMessage(), ex);
                }
            });
            log.debug("await number after: {}", barrier.getNumberWaiting());
            sleep(2.5);
        }
        service.shutdown();

    }

    private static void test1() {
        ExecutorService service = Executors.newFixedThreadPool(5);
        for (int i = 0; i < 3; i++) {
            CountDownLatch latch = new CountDownLatch(2);
            service.submit(() -> {
                log.debug("task1 start...");
                sleep(1);
                latch.countDown();
            });
            service.submit(() -> {
                log.debug("task2 start...");
                sleep(2);
                latch.countDown();
            });
            try {
                latch.await();
            } catch (InterruptedException ex) {
                log.error("exception: [{}]", ex.getMessage(), ex);
            }
            log.debug("task1 task2 finish...");
        }
        service.shutdown();
    }
}
